/**
 * @Author Fizz Pu
 * @Date 2020/9/22 下午8:58
 * @Version 1.0
 * 失之毫厘，缪之千里！
 */

/**
 * 给定一个数组 nums 和滑动窗口的大小 k，请找出所有滑动窗口里的最大值。
 *
 * 示例:
 *
 * 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
 * 输出: [3,3,5,5,6,7]
 * 解释:
 *
 *   滑动窗口的位置                最大值
 * ---------------               -----
 * [1  3  -1] -3  5  3  6  7       3
 *  1 [3  -1  -3] 5  3  6  7       3
 *  1  3 [-1  -3  5] 3  6  7       5
 *  1  3  -1 [-3  5  3] 6  7       5
 *  1  3  -1  -3 [5  3  6] 7       6
 *  1  3  -1  -3  5 [3  6  7]      7
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */

import java.util.*;

public class Lee59 {
    public static void main(String[] args) {
        System.out.println(Arrays.toString(maxSlidingWindow(new int[]{1,3,-1,-3,5,3,6,7}, 3)));
    }


    public static int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length <= 0 || k <= 0) {
            return new int[0];
        }

        int len = nums.length;
        // k有效不需要校验k
        int[] res = new int[len - k + 1];
        
        // 双端队列
        LinkedList<Integer> cache = new LinkedList<>();
        
        for (int i=0; i<len; i++) {
            // 添加元素到队列，保证队列递增,比当前元素小的都弹出
            // 队列为空直接入队
            // 队列不为空nums[i]加入到合适位置，保证有序
            while (!cache.isEmpty() && nums[cache.peekLast()] < nums[i]) {
                // 队列中加入元素索引
                cache.removeLast();
            }

            // 队列中加入元素索引
            // 为空或者比队尾小
            cache.addLast(i);
            
            // 需要移除队列中过期的元素
            // peekFirst是最大元素， 最多k个
            // ？
            if (i - cache.peekFirst() >= k) {
                cache.removeFirst();
            }

            // 如果队列中i>=k-1, 记录当前队列中的最大值
            if (i >= k - 1) {
                res[i-k+1] = nums[cache.peekFirst()];
            }
        }
        
        return res;
    }
}
